use std::{rc::Rc, cell::RefCell};

use crate::{rtda::Frame, instructions::base::{Instruction, BytecodeReader}};


// dload指令的索引来自操作数，其他来自指令
// Load double from local variable
#[derive(Debug, Default)]
pub struct DLOAD {
    index: usize
}

impl Instruction for DLOAD {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u8() as usize;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _dload(frame, self.index);
    }
}

impl DLOAD {
    pub fn set_index(&mut self, index: usize) {
        self.index = index;
    } 
}

#[derive(Debug, Default)]
pub struct DLOAD_0 { }

impl Instruction for DLOAD_0 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _dload(frame, 0);
    }
}

#[derive(Debug, Default)]
pub struct DLOAD_1 { }

impl Instruction for DLOAD_1 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _dload(frame, 1);
    }
}

#[derive(Debug, Default)]
pub struct DLOAD_2 { }

impl Instruction for DLOAD_2 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _dload(frame, 2);
    }
}

#[derive(Debug, Default)]
pub struct DLOAD_3 { }

impl Instruction for DLOAD_3 {
    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        _dload(frame, 3);
    }
}

// 通用加载，从局部变量表获取变量，推入操作数栈顶
fn _dload(frame: Rc<RefCell<Frame>>, index: usize) {
    let val = frame.borrow().get_local_vars().borrow().get_double(index);
    frame.borrow().get_operand_stack().borrow_mut().push_double(val);
}